﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

using SmlEngine;
using SmlEngine.Graphics;
using SmlEngine.Extensions;

namespace SmlEngine.Sprites.Base.WorldMap
{
    /// <summary>
    /// Path tiles for the world map.  The player can walk over these tiles.
    /// </summary>
    public class PathTile : ICloneable, IGameObject
    {
        #region Properties and Fields
        public Vector2 Position { get; set; }
        private Vector2 size;
        public Visibility Visibility
        {
            get
            {
                return Sprites.Visibility.Visible;
            }
            set
            {
                throw new NotImplementedException();
            }
        }
        public WorldTile worldTile { get; protected set; }

        /// <summary>
        /// The number of the exit that reveals this tile once triggered.
        /// </summary>
        public virtual int exitNumber { get; protected set; }
        private bool isRevealing = false;
        public virtual bool IsRevealed
        {
            get
            {
                return worldTile.TransparencyMultiplier == 1.0f;
            }
        }

        public PathType Direction { get; set; }

        public bool IsAnimated { get; set; }

        /// <summary>
        /// Determines whether this path should stop the player.
        /// </summary>
        public virtual bool IsNode { get; protected set; }

        public virtual Vector2 Size
        {
            get
            {
                if (worldTile.Size != new Vector2(float.NaN, float.NaN))
                {
                    return worldTile.Size;
                }
                else return new Vector2(16, 16);
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public Rectangle Area
        {
            get
            {
                return new Rectangle((int)Position.X, (int)Position.Y, (int)Size.X, (int)Size.Y);
            }
        }

        public Vector2 tilePosition
        {
            get
            {
                return new Vector2((float)Math.Floor(Position.X / 16), (float)Math.Floor(Position.Y / 16));
            }
        }

        private bool isDataSet = false;
        #endregion

        #region Constructors
        public PathTile() { }

        /// <summary>
        /// Creates a new Path tile that uses one texture of animation.
        /// </summary>
        /// <param name="cm">The ContentManager to use.</param>
        /// <param name="gd">The GraphicsDevice to use.</param>
        /// <param name="source">The source of the graphic.</param>
        /// <param name="texturePos">The position of the texture on the graphic.</param>
        /// <param name="tileSize">How large the tile is.</param>
        /// <param name="direction">The direction the tile faces.</param>
        /// <param name="node">Whether or not this tile is a node.</param>
        /// <param name="startPosition">The position to put the tile at onscreen.</param>
        /// <param name="startRevealed">Whether the tile should be revealed on load.</param>
        public PathTile(ContentManager cm, GraphicsDevice gd, string source, Vector2 texturePos, Vector2 tileSize, PathType direction, bool node)
        {
            worldTile = new WorldTile(source, texturePos.ToRectangle(tileSize).ToRectList());
            IsAnimated = false;

            size = tileSize;
            Direction = direction;
            IsNode = node;
        }

        /// <summary>
        /// Creates an animated Path tile.
        /// </summary>
        /// <param name="cm">The ContentManager to use.</param>
        /// <param name="gd">The GraphicsDevice to use.</param>
        /// <param name="source">The source of the graphic.</param>
        /// <param name="texturePos">The positions of the textures on the graphic.</param>
        /// <param name="tileSize">The size of the tile on the graphic.</param>
        /// <param name="startPosition">The onscreen position to draw at.</param>
        /// <param name="frameTime">The amount of frames to draw each Texture.</param>
        /// <param name="node">Whether or not this tile is a node.</param>
        /// <param name="startRevealed">Determines whether the tile is automatically revealed.</param>
        public PathTile(ContentManager cm, GraphicsDevice gd, string source, List<Vector2> texturePos, Vector2 tileSize, PathType direction, int frameTime, bool node)
        {
            worldTile = new WorldTile(source, texturePos.ToRectangleList(tileSize));
            IsAnimated = true;
            //LoadContent(gd, cm);

            size = tileSize;
            Direction = direction;
            IsNode = node;
        }
        #endregion

        #region Update and Draw
        public virtual void Update(GameTime gameTime)
        {
            if (worldTile.TransparencyMultiplier != 1.0f && !IsRevealed && exitNumber == -1) worldTile.TransparencyMultiplier = 1.0f;
            if (isRevealing && worldTile.TransparencyMultiplier < 1.0f)
            {
                worldTile.TransparencyMultiplier += 0.05f;
            }
        }

        public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            worldTile.Draw(gameTime, spriteBatch, Position);
        }
        #endregion

        #region Methods
        /// <summary>
        /// Starts revealing the tile.
        /// </summary>
        public void Reveal()
        {
            if (!IsRevealed) isRevealing = true;
        }

        public Object Clone()
        {
            PathTile p = new PathTile();
            p.worldTile = worldTile.Clone();
            p.Direction = Direction;
            p.Position = Position;
            p.size = size;
            return p;
        }

        public void LoadContent(ContentManager cm, GraphicsDevice gd)
        {
            worldTile.LoadContent(gd, cm, IsAnimated);
        }

        public void UnloadContent()
        {
            worldTile.UnloadContent();
        }

        public void Initialize() { }

        public void SetData(Vector2 position, int c_exitNumber)
        {
            if (!isDataSet)
            {
                Position = position;
                exitNumber = c_exitNumber;
                if (worldTile != null)
                {
                    if (exitNumber == -1) worldTile.TransparencyMultiplier = 1.0f;
                    else worldTile.TransparencyMultiplier = 0.0f;
                }
                isDataSet = true;
            }
        }

        public void SetData(int c_exitNumber)
        {
            exitNumber = c_exitNumber;
            if (exitNumber == -1) worldTile.TransparencyMultiplier = 1.0f;
            else worldTile.TransparencyMultiplier = 0.0f;
        }

        protected void SetFrameLength(int frameTime)
        {
            worldTile.SetData(frameTime);
        }
        #endregion
    }
}
